<template>
  <div>
    <h2>父组件</h2>
    <div>
      <h3>父组件中的数据：</h3>
      <p>收到的消息: {{ message }}</p>
      <p>计数器: {{ counter }}</p>
    </div>
    <!-- 监听子组件触发的自定义事件 -->
    <Child 
      v-on:message="handleMessage" 
      @increment="handleIncrement" 
    />
  </div>
</template>

<script lang="ts" setup>
/**
 * 自定义事件详解 - 父组件部分
 * 
 * 1. 监听子组件事件：
 *    - 使用v-on指令（@简写）监听子组件触发的事件
 *    - 可以直接绑定方法名，也可以使用内联语句
 * 
 * 2. 事件处理方式：
 *    2.1 方法处理（推荐）：
 *        @event-name="handleEvent"
 *    
 *    2.2 内联处理：
 *        @event-name="(payload) => {  处理逻辑  }"
 * 
 * 3. 接收事件参数：
 *    - 事件处理函数会自动接收子组件传递的参数
 *    - 可以接收多个参数
 * 
 * 4. 使用场景：
 *    4.1 表单提交：子组件触发submit事件，传递表单数据
 *    4.2 用户交互：按钮点击、输入完成等操作通知父组件
 *    4.3 状态变更：子组件内部状态变化时通知父组件
 *    4.4 子组件生命周期事件：如加载完成、数据准备就绪等
 * 
 * 5. 与v-model的关系：
 *    - v-model本质上是props和事件的语法糖
 *    - v-model="value"相当于:model-value="value" @update:model-value="value = $event"
 * 
 * 6. 最佳实践：
 *    6.1 事件命名使用kebab-case（如update-value）
 *    6.2 复杂数据使用对象传递，而不是多个参数
 *    6.3 明确事件的用途和传递的数据类型
 *    6.4 避免过度使用事件，考虑其他通信方式如props、provide/inject
 */

import { ref } from 'vue';
import Child from './child.vue';

// 用于存储子组件传递的数据
const message = ref('暂无消息');
const counter = ref(0);

// 处理子组件触发的message事件
function handleMessage(msg: string) {
  message.value = msg;
  console.log('收到子组件消息:', msg);
}

// 处理子组件触发的increment事件
function handleIncrement(value: number) {
  counter.value += value;
  console.log('计数器增加:', value);
}

/**
 * 7. 事件验证：
 *    - 子组件可以对事件参数进行验证
 *    - 父组件应当处理可能的无效数据
 * 
 * 8. 事件修饰符：
 *    - 自定义事件不支持原生事件的修饰符（如.prevent）
 *    - 但可以在事件处理函数中实现类似功能
 * 
 * 9. 与其他通信方式的对比：
 *    - Props：父→子通信
 *    - 事件：子→父通信
 *    - v-model：双向绑定（props+事件的语法糖）
 *    - provide/inject：跨多级组件通信
 *    - Vuex/Pinia：全局状态管理
 */
</script>

<style scoped>
/* 父组件样式 */
div {
  background: linear-gradient(to right, #8e2de2, #4a00e0);
  border-radius: 15px;
  padding: 30px;
  color: white;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  max-width: 800px;
  margin: 20px auto;
}

h2 {
  font-size: 28px;
  margin-bottom: 25px;
  text-align: center;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
  position: relative;
  padding-bottom: 15px;
}

h2::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100px;
  height: 3px;
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 3px;
}

p {
  font-size: 18px;
  margin: 10px 0;
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.1);
  border-radius: 8px;
}
</style>